#include "gtkcssnodeprivate.h"
#include "gtkcssanimatedstyleprivate.h"
+#include "gtkcsssectionprivate.h"
+#include "gtkcssstylepropertyprivate.h"
#include "gtkdebug.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtksettingsprivate.h"
#include "gtktypebuiltins.h"
-#include "gtkcssstylepropertyprivate.h"
-#include "gtkcsssectionprivate.h"
/*
* CSS nodes are the backbone of the GtkStyleContext implementation and
static guint cssnode_signals[LAST_SIGNAL] = { 0 };
static GParamSpec *cssnode_properties[NUM_PROPERTIES];
-static GQuark quark_global_cache;
-
static GtkStyleProviderPrivate *
gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
{
return TRUE;
}
-#define UNPACK_DECLARATION(packed) ((GtkCssNodeDeclaration *) (GPOINTER_TO_SIZE (packed) & ~0x3))
-#define UNPACK_FLAGS(packed) (GPOINTER_TO_SIZE (packed) & 0x3)
-#define PACK(decl, first_child, last_child) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (decl) | ((first_child) ? 0x2 : 0) | ((last_child) ? 0x1 : 0))
-
static gboolean
may_use_global_parent_cache (GtkCssNode *node)
{
static GtkCssStyle *
lookup_in_global_parent_cache (GtkCssNode *node,
- GtkCssStyle *parent,
const GtkCssNodeDeclaration *decl)
{
- GHashTable *cache;
- GtkCssStyle *style;
+ GtkCssNode *parent;
+
+ parent = node->parent;
if (parent == NULL ||
!may_use_global_parent_cache (node))
return NULL;
- cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
- if (cache == NULL)
+ if (parent->cache == NULL)
return NULL;
- style = g_hash_table_lookup (cache,
- PACK (decl,
- gtk_css_node_is_first_child (node),
- gtk_css_node_is_last_child (node)));
-
- return style;
-}
-
-static gboolean
-may_be_stored_in_parent_cache (GtkCssStyle *style)
-{
- GtkCssChange change;
-
- change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
-
- /* The cache is shared between all children of the parent, so if a
- * style depends on a sibling it is not independant of the child.
- */
- if (change & GTK_CSS_CHANGE_ANY_SIBLING)
- return FALSE;
-
- /* Again, the cache is shared between all children of the parent.
- * If the position is relevant, no child has the same style.
- */
- if (change & (GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD))
- return FALSE;
-
- return TRUE;
-}
-
-static guint
-gtk_global_parent_cache_hash (gconstpointer item)
-{
- return gtk_css_node_declaration_hash (UNPACK_DECLARATION (item)) << 2
- | UNPACK_FLAGS (item);
-}
-
-static gboolean
-gtk_global_parent_cache_equal (gconstpointer item1,
- gconstpointer item2)
-{
- if (UNPACK_FLAGS (item1) != UNPACK_FLAGS (item2))
- return FALSE;
-
- return gtk_css_node_declaration_equal (UNPACK_DECLARATION (item1),
- UNPACK_DECLARATION (item2));
-}
+ node->cache = gtk_css_node_style_cache_lookup (parent->cache,
+ (GtkCssNodeDeclaration *) decl,
+ gtk_css_node_is_first_child (node),
+ gtk_css_node_is_last_child (node));
+ if (node->cache == NULL)
+ return NULL;
-static void
-gtk_global_parent_cache_free (gpointer item)
-{
- gtk_css_node_declaration_unref (UNPACK_DECLARATION (item));
+ return gtk_css_node_style_cache_get_style (node->cache);
}
static void
store_in_global_parent_cache (GtkCssNode *node,
- GtkCssStyle *parent,
const GtkCssNodeDeclaration *decl,
GtkCssStyle *style)
{
- GHashTable *cache;
+ GtkCssNode *parent;
g_assert (GTK_IS_CSS_STATIC_STYLE (style));
+ parent = node->parent;
+
if (parent == NULL ||
!may_use_global_parent_cache (node))
return;
- if (!may_be_stored_in_parent_cache (style))
- return;
-
- cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
- if (cache == NULL)
- {
- cache = g_hash_table_new_full (gtk_global_parent_cache_hash,
- gtk_global_parent_cache_equal,
- gtk_global_parent_cache_free,
- g_object_unref);
- g_object_set_qdata_full (G_OBJECT (parent),
- quark_global_cache,
- cache,
- (GDestroyNotify) g_hash_table_destroy);
- }
+ if (parent->cache == NULL)
+ parent->cache = gtk_css_node_style_cache_new (parent->style);
- g_hash_table_insert (cache,
- PACK (gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl),
- gtk_css_node_is_first_child (node),
- gtk_css_node_is_last_child (node)),
- g_object_ref (style));
+ node->cache = gtk_css_node_style_cache_insert (parent->cache,
+ (GtkCssNodeDeclaration *) decl,
+ gtk_css_node_is_first_child (node),
+ gtk_css_node_is_last_child (node),
+ style);
}
static GtkCssStyle *
decl = gtk_css_node_get_declaration (cssnode);
parent = cssnode->parent ? cssnode->parent->style : NULL;
- style = lookup_in_global_parent_cache (cssnode, parent, decl);
+ style = lookup_in_global_parent_cache (cssnode, decl);
if (style)
return g_object_ref (style);
NULL,
parent);
- store_in_global_parent_cache (cssnode, parent, decl, style);
+ store_in_global_parent_cache (cssnode, decl, style);
return style;
}
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- quark_global_cache = g_quark_from_static_string ("gtk-global-cache");
-
object_class->get_property = gtk_css_node_get_property;
object_class->set_property = gtk_css_node_set_property;
object_class->dispose = gtk_css_node_dispose;
if (cssnode->previous_sibling)
gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
+ g_clear_pointer (&cssnode->cache, gtk_css_node_style_cache_unref);
+
new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
cssnode->pending_changes,
current_time,
style_changed = gtk_css_node_set_style (cssnode, new_style);
g_object_unref (new_style);
-
- if (!style_changed && (cssnode->pending_changes & GTK_CSS_CHANGE_SOURCE))
- {
- /* clear the global cache if we reuse the same style after the CSS changed */
- g_object_set_qdata (G_OBJECT (cssnode->style), quark_global_cache, NULL);
- }
}
else
{
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2015 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkcssnodestylecacheprivate.h"
+
+struct _GtkCssNodeStyleCache {
+ guint ref_count;
+ GtkCssStyle *style;
+ GHashTable *children;
+};
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_new (GtkCssStyle *style)
+{
+ GtkCssNodeStyleCache *result;
+
+ result = g_slice_new0 (GtkCssNodeStyleCache);
+
+ result->ref_count = 1;
+ result->style = g_object_ref (style);
+
+ return result;
+}
+
+void
+gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache)
+{
+ cache->ref_count--;
+
+ if (cache->ref_count > 0)
+ return;
+
+ g_object_unref (cache->style);
+}
+
+GtkCssStyle *
+gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache)
+{
+ return cache->style;
+}
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
+ GtkCssNodeDeclaration *decl,
+ gboolean is_first,
+ gboolean is_last,
+ GtkCssStyle *style)
+{
+ return gtk_css_node_style_cache_new (style);
+}
+
+GtkCssNodeStyleCache *
+gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache *parent,
+ GtkCssNodeDeclaration *decl,
+ gboolean is_first,
+ gboolean is_last)
+{
+ return NULL;
+}
+
--- /dev/null
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2016 Benjamin Otte <otte@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
+#define __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
+
+#include "gtkcssstyleprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkCssNodeStyleCache GtkCssNodeStyleCache;
+
+GtkCssNodeStyleCache * gtk_css_node_style_cache_new (GtkCssStyle *style);
+void gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache);
+
+GtkCssStyle * gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache);
+
+GtkCssNodeStyleCache * gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
+ GtkCssNodeDeclaration *decl,
+ gboolean is_first,
+ gboolean is_last,
+ GtkCssStyle *style);
+GtkCssNodeStyleCache * gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache *parent,
+ GtkCssNodeDeclaration *decl,
+ gboolean is_first,
+ gboolean is_last);
+
+G_END_DECLS
+
+#endif /* __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__ */